/**
 * 无障碍和触摸交互工具
 * 提供统一的无障碍支持和触摸优化
 */

/**
 * 触摸目标最小尺寸（rpx）
 */
export const MIN_TOUCH_TARGET_SIZE = 88

/**
 * 触摸反馈延迟（毫秒）
 */
export const TOUCH_FEEDBACK_DELAY = 100

/**
 * 无障碍角色类型
 */
export enum AriaRole {
  BUTTON = 'button',
  LINK = 'link',
  TEXTBOX = 'textbox',
  CHECKBOX = 'checkbox',
  RADIO = 'radio',
  TAB = 'tab',
  TABPANEL = 'tabpanel',
  DIALOG = 'dialog',
  ALERT = 'alert',
  STATUS = 'status',
  PROGRESSBAR = 'progressbar',
  SLIDER = 'slider',
  SPINBUTTON = 'spinbutton',
  COMBOBOX = 'combobox',
  LISTBOX = 'listbox',
  OPTION = 'option',
  MENU = 'menu',
  MENUITEM = 'menuitem',
  NAVIGATION = 'navigation',
  MAIN = 'main',
  BANNER = 'banner',
  CONTENTINFO = 'contentinfo',
  COMPLEMENTARY = 'complementary',
  FORM = 'form',
  SEARCH = 'search'
}

/**
 * 无障碍属性接口
 */
export interface AccessibilityProps {
  role?: AriaRole
  label?: string
  describedBy?: string
  expanded?: boolean
  selected?: boolean
  checked?: boolean
  disabled?: boolean
  required?: boolean
  invalid?: boolean
  live?: 'off' | 'polite' | 'assertive'
  atomic?: boolean
  busy?: boolean
  hidden?: boolean
  level?: number
  valueNow?: number
  valueMin?: number
  valueMax?: number
  valueText?: string
}

/**
 * 触摸交互配置接口
 */
export interface TouchConfig {
  minSize?: number
  feedbackDelay?: number
  hapticFeedback?: boolean
  preventDoubleClick?: boolean
  longPressDelay?: number
}

/**
 * 生成无障碍属性
 * @param props 无障碍属性配置
 * @returns 属性对象
 */
export function generateAccessibilityProps(props: AccessibilityProps): Record<string, any> {
  const attrs: Record<string, any> = {}
  
  if (props.role) attrs.role = props.role
  if (props.label) attrs['aria-label'] = props.label
  if (props.describedBy) attrs['aria-describedby'] = props.describedBy
  if (props.expanded !== undefined) attrs['aria-expanded'] = props.expanded
  if (props.selected !== undefined) attrs['aria-selected'] = props.selected
  if (props.checked !== undefined) attrs['aria-checked'] = props.checked
  if (props.disabled !== undefined) attrs['aria-disabled'] = props.disabled
  if (props.required !== undefined) attrs['aria-required'] = props.required
  if (props.invalid !== undefined) attrs['aria-invalid'] = props.invalid
  if (props.live) attrs['aria-live'] = props.live
  if (props.atomic !== undefined) attrs['aria-atomic'] = props.atomic
  if (props.busy !== undefined) attrs['aria-busy'] = props.busy
  if (props.hidden !== undefined) attrs['aria-hidden'] = props.hidden
  if (props.level !== undefined) attrs['aria-level'] = props.level
  if (props.valueNow !== undefined) attrs['aria-valuenow'] = props.valueNow
  if (props.valueMin !== undefined) attrs['aria-valuemin'] = props.valueMin
  if (props.valueMax !== undefined) attrs['aria-valuemax'] = props.valueMax
  if (props.valueText) attrs['aria-valuetext'] = props.valueText
  
  return attrs
}

/**
 * 生成触摸优化样式类
 * @param config 触摸配置
 * @returns 样式类字符串
 */
export function generateTouchClasses(config: TouchConfig = {}): string {
  const {
    minSize = MIN_TOUCH_TARGET_SIZE,
    feedbackDelay = TOUCH_FEEDBACK_DELAY
  } = config
  
  const classes = [
    `min-h-[${minSize}rpx]`,
    `min-w-[${minSize}rpx]`,
    'touch-manipulation',
    'select-none',
    'transition-all',
    `duration-[${feedbackDelay}ms]`,
    'active:scale-95',
    'active:opacity-80',
    'focus:outline-none',
    'focus:ring-2',
    'focus:ring-blue-500',
    'focus:ring-opacity-50'
  ]
  
  return classes.join(' ')
}

/**
 * 触摸交互管理器
 */
export class TouchInteractionManager {
  private touchStartTime = 0
  private touchStartPosition = { x: 0, y: 0 }
  private isLongPress = false
  private longPressTimer: NodeJS.Timeout | null = null
  private preventDoubleClick = false
  private lastClickTime = 0
  
  constructor(private config: TouchConfig = {}) {}
  
  /**
   * 处理触摸开始
   * @param event 触摸事件
   * @param onLongPress 长按回调
   */
  handleTouchStart(
    event: any,
    onLongPress?: () => void
  ) {
    this.touchStartTime = Date.now()
    this.touchStartPosition = {
      x: event.touches?.[0]?.clientX || 0,
      y: event.touches?.[0]?.clientY || 0
    }
    this.isLongPress = false
    
    // 设置长按定时器
    if (onLongPress && this.config.longPressDelay) {
      this.longPressTimer = setTimeout(() => {
        this.isLongPress = true
        onLongPress()
      }, this.config.longPressDelay)
    }
  }
  
  /**
   * 处理触摸移动
   * @param event 触摸事件
   */
  handleTouchMove(event: any) {
    if (!this.longPressTimer) return
    
    const currentPosition = {
      x: event.touches?.[0]?.clientX || 0,
      y: event.touches?.[0]?.clientY || 0
    }
    
    // 计算移动距离
    const distance = Math.sqrt(
      Math.pow(currentPosition.x - this.touchStartPosition.x, 2) +
      Math.pow(currentPosition.y - this.touchStartPosition.y, 2)
    )
    
    // 如果移动距离超过阈值，取消长按
    if (distance > 10) {
      this.cancelLongPress()
    }
  }
  
  /**
   * 处理触摸结束
   * @param event 触摸事件
   * @param onClick 点击回调
   */
  handleTouchEnd(
    event: any,
    onClick?: () => void
  ) {
    this.cancelLongPress()
    
    // 如果是长按，不触发点击
    if (this.isLongPress) {
      return
    }
    
    // 防止双击
    if (this.config.preventDoubleClick) {
      const now = Date.now()
      if (now - this.lastClickTime < 300) {
        return
      }
      this.lastClickTime = now
    }
    
    // 触发点击回调
    if (onClick) {
      // 添加触摸反馈延迟
      setTimeout(() => {
        onClick()
      }, this.config.feedbackDelay || TOUCH_FEEDBACK_DELAY)
    }
  }
  
  /**
   * 取消长按
   */
  private cancelLongPress() {
    if (this.longPressTimer) {
      clearTimeout(this.longPressTimer)
      this.longPressTimer = null
    }
  }
  
  /**
   * 清理资源
   */
  destroy() {
    this.cancelLongPress()
  }
}

/**
 * 焦点管理器
 */
export class FocusManager {
  private focusableElements: HTMLElement[] = []
  private currentFocusIndex = -1
  
  /**
   * 初始化焦点管理
   * @param container 容器元素
   */
  init(container: HTMLElement) {
    this.updateFocusableElements(container)
  }
  
  /**
   * 更新可聚焦元素列表
   * @param container 容器元素
   */
  updateFocusableElements(container: HTMLElement) {
    const selector = [
      'button:not([disabled])',
      'input:not([disabled])',
      'textarea:not([disabled])',
      'select:not([disabled])',
      'a[href]',
      '[tabindex]:not([tabindex="-1"])'
    ].join(', ')
    
    this.focusableElements = Array.from(container.querySelectorAll(selector))
    this.currentFocusIndex = -1
  }
  
  /**
   * 聚焦到下一个元素
   */
  focusNext() {
    if (this.focusableElements.length === 0) return
    
    this.currentFocusIndex = (this.currentFocusIndex + 1) % this.focusableElements.length
    this.focusableElements[this.currentFocusIndex]?.focus()
  }
  
  /**
   * 聚焦到上一个元素
   */
  focusPrevious() {
    if (this.focusableElements.length === 0) return
    
    this.currentFocusIndex = this.currentFocusIndex <= 0 
      ? this.focusableElements.length - 1 
      : this.currentFocusIndex - 1
    this.focusableElements[this.currentFocusIndex]?.focus()
  }
  
  /**
   * 聚焦到第一个元素
   */
  focusFirst() {
    if (this.focusableElements.length === 0) return
    
    this.currentFocusIndex = 0
    this.focusableElements[0]?.focus()
  }
  
  /**
   * 聚焦到最后一个元素
   */
  focusLast() {
    if (this.focusableElements.length === 0) return
    
    this.currentFocusIndex = this.focusableElements.length - 1
    this.focusableElements[this.currentFocusIndex]?.focus()
  }
}

/**
 * 键盘导航处理器
 */
export class KeyboardNavigationHandler {
  constructor(private focusManager: FocusManager) {}
  
  /**
   * 处理键盘事件
   * @param event 键盘事件
   */
  handleKeyDown(event: KeyboardEvent) {
    switch (event.key) {
      case 'Tab':
        if (event.shiftKey) {
          event.preventDefault()
          this.focusManager.focusPrevious()
        } else {
          event.preventDefault()
          this.focusManager.focusNext()
        }
        break
        
      case 'Home':
        event.preventDefault()
        this.focusManager.focusFirst()
        break
        
      case 'End':
        event.preventDefault()
        this.focusManager.focusLast()
        break
        
      case 'ArrowDown':
        event.preventDefault()
        this.focusManager.focusNext()
        break
        
      case 'ArrowUp':
        event.preventDefault()
        this.focusManager.focusPrevious()
        break
    }
  }
}

/**
 * 屏幕阅读器公告管理器
 */
export class ScreenReaderAnnouncer {
  private announceElement: HTMLElement | null = null
  
  /**
   * 初始化公告元素
   */
  init() {
    if (this.announceElement) return
    
    this.announceElement = document.createElement('div')
    this.announceElement.setAttribute('aria-live', 'polite')
    this.announceElement.setAttribute('aria-atomic', 'true')
    this.announceElement.style.position = 'absolute'
    this.announceElement.style.left = '-10000px'
    this.announceElement.style.width = '1px'
    this.announceElement.style.height = '1px'
    this.announceElement.style.overflow = 'hidden'
    
    document.body.appendChild(this.announceElement)
  }
  
  /**
   * 公告消息
   * @param message 消息内容
   * @param priority 优先级
   */
  announce(message: string, priority: 'polite' | 'assertive' = 'polite') {
    if (!this.announceElement) {
      this.init()
    }
    
    if (this.announceElement) {
      this.announceElement.setAttribute('aria-live', priority)
      this.announceElement.textContent = message
      
      // 清空内容以便下次公告
      setTimeout(() => {
        if (this.announceElement) {
          this.announceElement.textContent = ''
        }
      }, 1000)
    }
  }
  
  /**
   * 清理资源
   */
  destroy() {
    if (this.announceElement) {
      document.body.removeChild(this.announceElement)
      this.announceElement = null
    }
  }
}

/**
 * 无障碍工具函数
 */
export const AccessibilityUtils = {
  /**
   * 检查元素是否可见
   * @param element 元素
   * @returns 是否可见
   */
  isElementVisible(element: HTMLElement): boolean {
    const style = window.getComputedStyle(element)
    return style.display !== 'none' && 
           style.visibility !== 'hidden' && 
           style.opacity !== '0'
  },
  
  /**
   * 获取元素的可访问名称
   * @param element 元素
   * @returns 可访问名称
   */
  getAccessibleName(element: HTMLElement): string {
    return element.getAttribute('aria-label') ||
           element.getAttribute('aria-labelledby') ||
           element.textContent ||
           element.getAttribute('title') ||
           ''
  },
  
  /**
   * 设置元素的可访问描述
   * @param element 元素
   * @param description 描述
   */
  setAccessibleDescription(element: HTMLElement, description: string) {
    const descId = `desc-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
    
    const descElement = document.createElement('div')
    descElement.id = descId
    descElement.textContent = description
    descElement.style.position = 'absolute'
    descElement.style.left = '-10000px'
    
    document.body.appendChild(descElement)
    element.setAttribute('aria-describedby', descId)
  }
}